#include "imageprocesser.h"

ImageProcesser::ImageProcesser(QImage *img)
{
    width = img->width();
    height = img->height();

    data = new unsigned char*[height];
    for (int i=0;i<height;i++){
        data[i] = new unsigned char[width];
    }

    ToGray(img);

}

ImageProcesser::~ImageProcesser()
{
    for (int i=0;i<height;i++){
        delete[] data[i];
    }
    delete[] data;
}

void ImageProcesser::ToGray(QImage *img){
    QRgb col;
    int gray;
    for (int i = 0; i < height; ++i)
    {
        for (int j = 0; j < width; ++j)
        {
            col = img->pixel(j, i);
            gray = qGray(col);
            data[i][j]=gray;
        }
    }
}

void ImageProcesser::Ecualize(){

    unsigned char d=255;
    unsigned char max=0;

    for (int i = 0; i < height; ++i)
    {
        for (int j = 0; j < width; ++j)
        {
            if(data[i][j]<d)
                d=data[i][j];
            if(data[i][j]>max)
                max=data[i][j];
        }
    }

    for (int i = 0; i < height; ++i)
    {
        for (int j = 0; j < width; ++j)
        {
            data[i][j] = (data[i][j]-d)*(255/(max-d));
        }
    }

}

void ImageProcesser::Threshold(int thres){

    for (int i = 0; i < height; ++i)
    {
        for (int j = 0; j < width; ++j)
        {
            if (data[i][j]<thres)
                data[i][j]=0;
            else
                data[i][j]=255;
        }
    }
}

unsigned char ImageProcesser::GetAutomaticThreshold(){

    unsigned char freqs[256];

    for(int i=0;i<256;i++)
        freqs[i]=0;

    for(int i=0;i<height;i++)
        for(int j=0;j<width;j++)
            freqs[data[i][j]]++; // podriem fer 0xFF & data[i][j] pero no cal

    int min=300;
    int thres=0;
    for (int i=50;i<125;i++)
        if(freqs[i] < min){
            min=freqs[i];
            thres=i;
        }

    return thres;
}

unsigned char ImageProcesser::GetOtsuThreshold(){

    unsigned char freqs[256];

    for(int i=0;i<256;i++)
        freqs[i]=0;

    for(int i=0;i<height;i++)
        for(int j=0;j<width;j++)
            freqs[data[i][j]]++;

    int total = height * width;

    float sum = 0;
    for(int i=0; i<256; i++) sum += i * freqs[i];

    float sumB = 0;
    int wB = 0;
    int wF = 0;

    float varMax = 0;
    int threshold = 0;

    for(int i=0 ; i<256 ; i++) {
        wB += freqs[i];
        if(wB == 0) continue;
        wF = total - wB;

        if(wF == 0) break;

        sumB += (float) (i * freqs[i]);
        float mB = sumB / wB;
        float mF = (sum - sumB) / wF;

        float varBetween = (float) wB * (float) wF * (mB - mF) * (mB - mF);

        if(varBetween > varMax) {
            varMax = varBetween;
            threshold = i;
        }
    }

    return threshold;

    return 1;

}

void ImageProcesser::Dilate(int num){
    unsigned char **aux;
    aux = new unsigned char*[height];
    for (int i=0;i<height;i++)
        aux[i] = new unsigned char[width];




    unsigned char BACKGROUND = 255;
    unsigned char OBJECT = 0;

    for(int n=0; n < num; n++){
        for (int i=0;i<height;i++)
            for(int j=0;j<width;j++)
                aux[i][j]=data[i][j];

        for (int i = 1; i < height-1; ++i){
            for (int j = 1; j < width-1; ++j){
                if (aux[i][j] == BACKGROUND &&
                    (aux[i-1][j-1] == OBJECT ||
                     aux[i-1][j  ] == OBJECT ||
                     aux[i-1][j+1] == OBJECT ||
                     aux[i  ][j-1] == OBJECT ||
                     aux[i  ][j+1] == OBJECT ||
                     aux[i+1][j-1] == OBJECT ||
                     aux[i+1][j  ] == OBJECT ||
                     aux[i+1][j+1] == OBJECT))
                    data[i][j] = OBJECT;
            }
        }
    }

    for (int i=0;i<height;i++){
        delete[] aux[i];
    }
    delete[] aux;
}

void ImageProcesser::Erode(int num){
    unsigned char **aux;
    aux = new unsigned char*[height];
    for (int i=0;i<height;i++)
        aux[i] = new unsigned char[width];




    unsigned char BACKGROUND = 255;
    unsigned char OBJECT = 0;

    for(int n=0; n < num; n++){
        for (int i=0;i<height;i++)
            for(int j=0;j<width;j++)
                aux[i][j]=data[i][j];

        for (int i = 1; i < height-1; ++i){
            for (int j = 1; j < width-1; ++j){
                if (aux[i][j] == OBJECT &&
                    (aux[i-1][j-1] == BACKGROUND ||
                     aux[i-1][j  ] == BACKGROUND ||
                     aux[i-1][j+1] == BACKGROUND ||
                     aux[i  ][j-1] == BACKGROUND ||
                     aux[i  ][j+1] == BACKGROUND ||
                     aux[i+1][j-1] == BACKGROUND ||
                     aux[i+1][j  ] == BACKGROUND ||
                     aux[i+1][j+1] == BACKGROUND))
                    data[i][j] = BACKGROUND;
            }
        }
    }

    for (int i=0;i<height;i++){
        delete[] aux[i];
    }
    delete[] aux;
}

QImage* ImageProcesser::GetImage(){
    QImage *image = new QImage(width,height,QImage::Format_RGB32);

    for (int i = 0; i < height; ++i)
    {
        for (int j = 0; j < width; ++j)
        {
            image->setPixel(j,i,qRgb(data[i][j],data[i][j],data[i][j]));
        }
    }

    return image;
}

int indi(int indice, int i){
   int pi;
   pi = 0;

   switch(indice){

      case 2:
         pi = 1;
         break;
      case 3:
         pi = 1;
         break;
      case 4:
         pi = 1;
         break;
      case 6:
         pi = -1;
         break;
      case 7:
         pi = -1;
         break;
      case 8:
         pi = -1;
         break;
      default:
         pi = 0;
   }
   return i+pi;

}

int indj(int indice, int j){
   int pj;
   pj = 0;

   switch(indice){
      case 1:
         pj = 1;
         break;
      case 2:
         pj = 1;
         break;
      case 4:
         pj = -1;
         break;
      case 5:
         pj = -1;
         break;
      case 6:
         pj = -1;
         break;
      case 8:
         pj = 1;
         break;
      default:
         pj = 0;
   }
   return j+pj;

}
int ImageProcesser::TagObjects(unsigned char **output){
   int N = 0;
   int finished;
   int found = 1;
   unsigned char A0;
   unsigned char P0,P1,P2,P3,P4,P5,P6,P7,P8;
   int i, j;
   int modo=0;




   for(i=0;i<height;i++){
      for(j=0;j<width;j++){
         output[i][j]=0;
      }
   }

   while(found){
      found = 0;

      for(i=1;i<height-1;i++){
         for(j=1;j<width-1;j++){
            A0 = data[indi(0,i)][indj(0,j)];
            P0 = output[indi(0,i)][indj(0,j)];
            if(A0<=40 && P0==0 && !found){
               N+=1;
               output[indi(0,i)][indj(0,j)] = N;
               found = 1;
               break;
            }
         }
         if(found)
            break;
      }

      if(found){
         finished = 0;
         while(!finished){

            finished = 1;
            if(modo==0){
               for(i=1;i<height-1;i++){
                  for(j=1;j<width-1;j++){
                     A0 = data[indi(0,i)][indj(0,j)];
                     P0 = output[indi(0,i)][indj(0,j)];
                     P1 = output[indi(1,i)][indj(1,j)];
                     P2 = output[indi(2,i)][indj(2,j)];
                     P3 = output[indi(3,i)][indj(3,j)];
                     P4 = output[indi(4,i)][indj(4,j)];
                     P5 = output[indi(5,i)][indj(5,j)];
                     P6 = output[indi(6,i)][indj(6,j)];
                     P7 = output[indi(7,i)][indj(7,j)];
                     P8 = output[indi(8,i)][indj(8,j)];

                     if(A0<=40 && P0==0 && (P1==N || P2==N ||
                                          P3==N || P4==N ||
                                          P5==N || P6==N ||
                                          P7==N || P8==N )){
                        output[indi(0,i)][indj(0,j)] = N;
                        finished = 0;
                     }
                  }
               }
            }else{
               for(i=height-2;i>=1;i--){
                  for(j=width-2;j>=1;j--){
                     A0 = data[indi(0,i)][indj(0,j)];
                     P0 = output[indi(0,i)][indj(0,j)];
                     P1 = output[indi(1,i)][indj(1,j)];
                     P2 = output[indi(2,i)][indj(2,j)];
                     P3 = output[indi(3,i)][indj(3,j)];
                     P4 = output[indi(4,i)][indj(4,j)];
                     P5 = output[indi(5,i)][indj(5,j)];
                     P6 = output[indi(6,i)][indj(6,j)];
                     P7 = output[indi(7,i)][indj(7,j)];
                     P8 = output[indi(8,i)][indj(8,j)];

                     if(A0<=40 && P0==0 && (P1==N || P2==N ||
                                          P3==N || P4==N ||
                                          P5==N || P6==N ||
                                          P7==N || P8==N )){
                        output[indi(0,i)][indj(0,j)] = N;
                        finished = 0;
                     }
                  }
               }
            }

            modo = 1-modo;
         }
      }
   }

   return N;
}


